package com.xbongbong.saas.help.workflow;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.dictionary.PaymentStatusEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.model.FundAccountModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
public class PayAndPaymentSheetHelp {

    private static final Logger LOG = LoggerFactory.getLogger(PayAndPaymentSheetHelp.class);

    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private FundAccountModel fundAccountModel;
    @Resource
    private UserModel userModel;

    /**
     * 更新父回/付款单时，同步更新子单
     * @param corpid 公司id
     * @param sheetTypeEnum 回款单类型
     * @param amountDetail 明细
     * @param explainMap 字段解释map
     * @return java.util.List<com.xbongbong.pro.domain.entity.UpdateDataEntity>
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public List<UpdateDataEntity> updateSonDataList4Sheet(String corpid, SheetTypeEnum sheetTypeEnum, Integer distributorMark, JSONArray amountDetail, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        if (CollectionsUtil.isEmpty(amountDetail) || amountDetail.size() <= BasicConstant.ONE) {
            return null;
        }
        Map<Long, JSONObject> idDataMap = new HashMap<>(amountDetail.size());
        List<Long> idIn = new ArrayList<>();
        for(Object obj : amountDetail){
            if (Objects.isNull(obj)) {
                continue;
            }
            JSONObject newData = null;
            if (obj instanceof HashMap) {
                newData = new JSONObject((HashMap)obj);
            } else {
                newData = (JSONObject)obj;
            }
            Long dataId = newData.getLong(StringConstant.DATA_ID);
            if (Objects.isNull(dataId)) {
                continue;
            }
            idDataMap.put(dataId, newData);
            idIn.add(dataId);
        }
        if (idIn.size() <= BasicConstant.ONE) {
            return null;
        }
        List<PaasFormDataEntityExt> childList = new ArrayList<>();
        switch (sheetTypeEnum.getXbbRefTypeEnum()) {
            case PAYMENT_SHEET:
                List<PaymentSheetEntityExt> paymentsheetList = paymentSheetModel.getPaymentSheetByIdIn(corpid, idIn);
                childList.addAll(paymentsheetList);
                break;
            case PAY_SHEET:
                List<PayPlanSheetEntityExt> paysheetList = payPlanSheetModel.getPaySheetByIdIn(corpid, idIn);
                childList.addAll(paysheetList);
                break;
            default:
                break;
        }
        if (childList.size() <= BasicConstant.ZERO) {
            return null;
        }
        List<UpdateDataEntity> updateList = new ArrayList<>();
        ValidateDataDTO validateDataDTO = new ValidateDataDTO();
        validateDataDTO.setBusinessType(sheetTypeEnum.getBusinessType());
        validateDataDTO.setExplainMap(explainMap);
        validateDataDTO.setNonCheckAmount(true);
        for (PaasFormDataEntityExt entityExt : childList) {
            Long dataId = entityExt.getId();
            JSONObject newData = idDataMap.get(dataId);
            if (Objects.isNull(newData)) {
                continue;
            }
            validateDataDTO.setData(newData);
            //处理一些自定义字段的格式（非自定义的不能更改）
            ProSaveHelp.analyticalData(validateDataDTO);
            JSONObject oldData = JsonHelperUtil.getJSONObject(entityExt.getData());
            //处理得到最终的data（禁止编辑字段，要移除字段处理）
            // TODO  合代码的问题
            JSONObject data = fundHelp.handlePaymentSheetData4Update(sheetTypeEnum, newData, oldData, distributorMark, explainMap);
            Set<String> newKeySet = data.keySet();
            Set<String> oldKeySet = oldData.keySet();
            oldKeySet.removeAll(newKeySet);
            oldKeySet.forEach(removeKey -> {
                newData.put(removeKey, null);
            });
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(dataId, data, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }


    public String handleStatus(Double planAmount, Double unAmount, Double badAmount, Double redAmount) {
        //"应收款"-丨"红冲应收"丨。由于红冲应收为负数，所以直接用add
        Double leftAmount = Arith.add(planAmount, redAmount);
        /*
         第一优先级：坏账、部分坏账优先级最高
         已坏账：当0＜"坏账金额"="应收款"-丨"红冲应收"丨；
         部分坏账：当0＜"坏账金额"＜"应收款"-丨"红冲应收"丨；
         */
        if (badAmount > 0 && Objects.equals(badAmount, leftAmount)) {
            //坏账金额等于应收款金额，则全部坏账，否则部分坏账
            return PaymentStatusEnum.BAD_DEBT.getCode();
        } else if (badAmount > 0) {
            return PaymentStatusEnum.PARTIAL_BAD_DEBT.getCode();
        }
        /*
         第二优先级：已未收状态
         未收款：当0＜"未收金额"，且="应收款"-丨"红冲应收"丨
         部分收款：当0＜"未收金额"，且＜"应收款"-丨"红冲应收"丨
         已收款：当"未收金额"=0;
         */
        /**
         * 2021.4.27修改后逻辑
         * 未收款小于等于0，就变成已收款
         * 未收款大于0，并且未收金额等于应收金额的胡，就是未收款
         * 其它就是部分已收
         */
        String planStatus;
        if (unAmount <= 0) {
            planStatus = PaymentStatusEnum.RECEIVABLES.getCode();
        }else if (unAmount > 0 && Objects.equals(unAmount, planAmount)) {
            planStatus = PaymentStatusEnum.UN_RECEIVABLES.getCode();
        }else {
            planStatus = PaymentStatusEnum.PARTIAL_RECEIPTS.getCode();
        }
        return planStatus;
    }

    /**
     * 更新资金账户数据
     *
     * @param accountId
     * @param amount
     * @param corpid
     * @throws XbbException
     */
    public void saveByPaymentSheetOrPaySheet(Long accountId, Double amount, String corpid) throws XbbException {
        try {
            fundAccountModel.updateAmount(corpid, accountId, amount);
        } catch (Exception e) {
            LOG.error("更新资金账户金额异常", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

}
